using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using OpenComposite.EII.Repository;
using OpenComposite.Repository.Properties;
using System.Xml;
using System.IO;
using System.Diagnostics;
using OpenComposite.Base.Collections;
using OpenComposite.EII.Forms;

namespace OpenComposite.EII.RepositoryUIs
{
	public partial class UCWorkflow : RepositoryItemUI
	{
		#region Initialization
		public UCWorkflow(IServiceProvider serviceProvider)
			: base(serviceProvider)
		{
			InitializeComponent();

			init();
		}
		private void init()
		{
		}
		#endregion

		#region Public Members

		#region Properties
		public override IRepositoryItem RepositoryItem
		{
			get
			{
				save();
				return _workflow;
			}
			set
			{
				if ( value is Repository.Workflow ) {
					OnBeforeRepositoryItemChanged();
					base.RepositoryItem = value;
					_workflow = (Repository.Workflow)value;
					load(true);
					OnAfterRepositoryItemChanged();
				}
			}
		}

		public override string TypeText
		{
			get
			{
				if ( _workflow != null ) {
					return _workflow.RepositoryItemTypeName;
				} else {
					return Resources.sWorkflow;
				}
			}
		}

		public override string TypeDescription
		{
			get { return ""; }
		}
		#endregion

		#endregion

		#region Protected Members

		#region Methods
		protected override void NotifyPropertyChange(string property, object value)
		{
			if ( property == "Name" && value != null ) {
				txtName.Text = value.ToString();
			}
		}
		protected override void OnBeforeRepositoryItemChanged()
		{
			Services.IRepositoryChangeService rcs = (Services.IRepositoryChangeService)
				this.GetService(typeof(Services.IRepositoryChangeService));
			Debug.Assert(rcs != null);
			rcs.RepositoryChanged -= new OpenComposite.EII.Services.RepositoryChangedEventHandler(rcs_RepositoryChanged);
			base.OnBeforeRepositoryItemChanged();
		}
		protected override void OnAfterRepositoryItemChanged()
		{
			Services.IRepositoryChangeService rcs = (Services.IRepositoryChangeService)
				this.GetService(typeof(Services.IRepositoryChangeService));
			Debug.Assert(rcs != null);
			rcs.RepositoryChanged += new OpenComposite.EII.Services.RepositoryChangedEventHandler(rcs_RepositoryChanged);
			base.OnAfterRepositoryItemChanged();
		}

		private void rcs_RepositoryChanged(object sender, OpenComposite.EII.Services.RepositoryChangedEventArgs e)
		{
			try {
				if ( this.Visible ) {
					if ( e.RepositoryItem != null ) {
						if ( e.RepositoryItem.Equals(_workflow) ) {
							load(false);
						} else {
							_changedSinceLastHierarchyView = true;
						}
					}
				}
			} catch { }
		}
		#endregion

		#endregion

		#region Private Members

		#region Variables
		private Repository.Workflow _workflow = null;
		private bool _changedSinceLastHierarchyView = false;
		#endregion

		#region Methods
		private void load(bool reload)
		{
			if ( _workflow == null ) return;
			if ( reload ) _workflow.Reload();

			txtName.Text = _workflow.Name;
			txtDesc.Text = _workflow.Description;

			txtName.Select(0, 0);
			txtName.ScrollToCaret();
			txtName.SelectAll();

			displayInputOutput();
			displayConfigurationFileLocations();
			displayDeployedWS();
		}
		private void save()
		{
			if ( _workflow == null ) return; // EXIT

			int inputid = _workflow.InputBusinessObjectID;
			int outputid = _workflow.OutputBusinessObjectID;
			string oldName = _workflow.StartName;
			int deplwsid = _workflow.DeployedWebServiceID;

			_workflow.Reload();
			_workflow.BeginEdit();
			_workflow.Name = txtName.Text;
			_workflow.Description = txtDesc.Text;

			if ( miURL.Checked ) {
				_workflow.ExtendedProperties.IsDeployedWebServiceURL = true;
				_workflow.ExtendedProperties.DeployedWebServiceURL = txtWebService.Text;
				_workflow.DeployedWebServiceID = -1;
			} else {
				_workflow.ExtendedProperties.IsDeployedWebServiceURL = false;
				_workflow.ExtendedProperties.DeployedWebServiceURL = "";
				_workflow.DeployedWebServiceID = deplwsid;
			}
			_workflow.EndEdit(false);
		}

		private void displayInputOutput()
		{
			if ( this.InvokeRequired ) {
				this.Invoke(new MethodInvoker(displayInputOutput));
			} else {
				BindingListEx<IWorkflowInterfaceItem> items = new BindingListEx<IWorkflowInterfaceItem>();
				foreach ( var item in _workflow.Interface.Fields ) items.Add(item);
				foreach ( var item in _workflow.Interface.Events ) items.Add(item);
				foreach ( var item in _workflow.Interface.Methods ) items.Add(item);
				dgvInterface.DataSource = items;
				dgvInterface.AutoResizeColumns();
			}
			#region Old Code
			//this.SuspendLayout();
			//txtStartInput.SuspendLayout();
			//txtStartOutput.SuspendLayout();
			//if ( _workflow.InputBusinessObject == null ) {
			//    txtStartInput.ForeColor = SystemColors.GrayText;
			//    txtStartInput.TextAlign = HorizontalAlignment.Center;
			//    txtStartInput.Text = "Please select an input.";
			//    btnStartRemoveInput.Enabled = false;
			//    btnStartViewInput.Enabled = false;
			//} else {
			//    txtStartInput.ForeColor = SystemColors.ControlText;
			//    txtStartInput.TextAlign = HorizontalAlignment.Left;
			//    txtStartInput.Text = _workflow.InputBusinessObject.Name;
			//    btnStartRemoveInput.Enabled = true;
			//    btnStartViewInput.Enabled = true;
			//}
			//if ( _workflow.OutputBusinessObject == null ) {
			//    txtStartOutput.ForeColor = SystemColors.GrayText;
			//    txtStartOutput.TextAlign = HorizontalAlignment.Center;
			//    txtStartOutput.Text = "Please select an output.";
			//    btnStartRemoveOutput.Enabled = false;
			//    btnStartViewOutput.Enabled = false;
			//} else {
			//    txtStartOutput.ForeColor = SystemColors.ControlText;
			//    txtStartOutput.TextAlign = HorizontalAlignment.Left;
			//    txtStartOutput.Text = _workflow.OutputBusinessObject.Name;
			//    btnStartRemoveOutput.Enabled = true;
			//    btnStartViewOutput.Enabled = true;
			//}
			//txtStartInput.ResumeLayout(false);
			//txtStartOutput.ResumeLayout(false);
			//this.ResumeLayout(true);
			#endregion
		}
		private void viewSchema(BusinessObject bo)
		{
			if ( bo == null || bo.Schema == null )
				return;

			XmlDocument xd = new XmlDocument();
			using ( StringWriter sw = new StringWriter() ) {
				bo.Schema.Write(sw);
				xd.LoadXml(sw.ToString());
			}
			formXmlViewer XmlViewer = new formXmlViewer();
			XmlViewer.XmlDocument = xd;
			XmlViewer.Text = "XML-Schema of Business Object \"" + bo.Name + "\"";
			XmlViewer.ShowDialog();
		}
		private void selectBusinessObject(bool isInput)
		{
			//BusinessObject resultBO = null;
			Forms.FormSelectRepositoryEx frm = new OpenComposite.EII.Forms.FormSelectRepositoryEx(_workflow);
			frm.AllowedTypes = new ItemType[] { ItemType.BObject };
			frm.DomainID = Global.Status.CurrentDomainId;
			frm.RepositoryID = Global.Status.CurrentRepositoryId;
			frm.MultiSelect = false;
			frm.SelectedItem = isInput ? _workflow.InputBusinessObject : _workflow.OutputBusinessObject;
			if ( frm.ShowDialog() == DialogResult.OK ) {
				if ( isInput ) {
					_workflow.InputBusinessObject = frm.SelectedItem as BusinessObject;
				} else {
					_workflow.OutputBusinessObject = frm.SelectedItem as BusinessObject;
				}
				displayInputOutput();
			}
		}
		private void displayConfigurationFileLocations()
		{
			lbLocations.BeginUpdate();
			lbLocations.Items.Clear();
			lbLocations.Items.AddRange(_workflow.ExtendedProperties.ConfigurationFileLocations.ToArray());
			lbLocations.EndUpdate();
		}
		private void displayDeployedWS()
		{
			txtWebService.SuspendLayout();
			if ( _workflow.ExtendedProperties.IsDeployedWebServiceURL ) {
				txtWebService.Text = _workflow.ExtendedProperties.DeployedWebServiceURL;
				miURL.Checked = true;
				miRepositoryWS.Checked = false;
				txtWebService.ReadOnly = false;
				txtWebService.TextAlign = HorizontalAlignment.Left;
				btnSelectWSType.Text = "URL";
				btnSelectWS.Enabled = false;
			} else {
				if ( _workflow.DeployedWebService != null ) {
					txtWebService.TextAlign = HorizontalAlignment.Left;
					txtWebService.Text = _workflow.DeployedWebService.Name;
				} else {
					txtWebService.TextAlign = HorizontalAlignment.Center;
					txtWebService.Text = "Please select the repository web service.";
				}
				miURL.Checked = false;
				miRepositoryWS.Checked = true;
				txtWebService.ReadOnly = true;
				btnSelectWSType.Text = "Repository WS";
				btnSelectWS.Enabled = true;
			}
			txtWebService.ResumeLayout(true);
		}

		#endregion

		#region Event Handlers

		private void btnStartSelInput_Click(object sender, EventArgs e)
		{
			selectBusinessObject(true);
		}
		private void btnStartViewInput_Click(object sender, EventArgs e)
		{
			viewSchema(_workflow.InputBusinessObject);
		}
		private void btnStartRemoveInput_Click(object sender, EventArgs e)
		{
			_workflow.InputBusinessObject = null;
			displayInputOutput();
		}

		private void btnStartSelOutput_Click(object sender, EventArgs e)
		{
			selectBusinessObject(false);
		}
		private void btnStartViewOutput_Click(object sender, EventArgs e)
		{
			viewSchema(_workflow.OutputBusinessObject);
		}
		private void btnStartRemoveOutput_Click(object sender, EventArgs e)
		{
			_workflow.OutputBusinessObject = null;
			displayInputOutput();
		}

		private void txtBO_DragOver(object sender, DragEventArgs e)
		{
			if ( e.Data.GetDataPresent(typeof(BusinessObject)) ) {
				e.Effect = DragDropEffects.Link;
			} else {
				e.Effect = DragDropEffects.None;
			}
		}
		private void txtBO_DragDrop(object sender, DragEventArgs e)
		{
			if ( e.Data.GetDataPresent(typeof(BusinessObject)) ) {
				BusinessObject bo = (BusinessObject)e.Data.GetData(typeof(BusinessObject));
				//if ( sender == txtStartInput ) {
				//    _workflow.InputBusinessObject = bo;
				//} else if ( sender == txtStartOutput ) {
				//    _workflow.OutputBusinessObject = bo;
				//}
				displayInputOutput();
			}
		}

		private void btnAddLocation_Click(object sender, EventArgs e)
		{
			dlgFolder.SelectedPath = string.Empty;
			if ( dlgFolder.ShowDialog() == DialogResult.OK ) {
				if ( !_workflow.ExtendedProperties.ConfigurationFileLocations.Contains(dlgFolder.SelectedPath) ) {
					_workflow.ExtendedProperties.ConfigurationFileLocations.Add(dlgFolder.SelectedPath);
					displayConfigurationFileLocations();
				}
			}
		}
		private void btnRemoveLocation_Click(object sender, EventArgs e)
		{
			foreach ( string item in lbLocations.SelectedItems ) {
				if ( _workflow.ExtendedProperties.ConfigurationFileLocations.Contains(item) ) {
					_workflow.ExtendedProperties.ConfigurationFileLocations.Remove(item);
				}
			}
			displayConfigurationFileLocations();
		}
		private void lbLocations_SelectedIndexChanged(object sender, EventArgs e)
		{
			btnRemoveLocation.Enabled = ( lbLocations.SelectedIndices.Count > 0 );
		}

		private void btnSelectWS_Click(object sender, EventArgs e)
		{
			FormSelectRepositoryEx frm = new FormSelectRepositoryEx(_workflow);
			frm.AllowedTypes = new ItemType[] { ItemType.WebService };
			frm.MultiSelect = false;
			frm.AllowChangeDomain = true;
			frm.AllowCreateNewItem = true;
			frm.SelectedItem = _workflow.DeployedWebService;
			if ( frm.ShowDialog() == DialogResult.OK ) {
				_workflow.DeployedWebService = frm.SelectedItem as WebService;
				displayDeployedWS();
			}
		}
		private void btnSelectWSType_Click(object sender, EventArgs e)
		{
			Point p = new Point(btnSelectWSType.Left, btnSelectWSType.Bottom);
			contextDeployedWSType.Show(btnSelectWSType.Parent.PointToScreen(p));
		}
		private void repositoryWebServiceToolStripMenuItem_Click(object sender, EventArgs e)
		{
			if ( !miRepositoryWS.Checked ) {
				_workflow.ExtendedProperties.IsDeployedWebServiceURL = false;
				displayDeployedWS();
				//miRepositoryWS.Checked = true;
				//miURL.Checked = false;
				//txtWebService.ReadOnly = true;
				//btnSelectWS.Enabled = true;
				//btnSelectWSType.Text = "Repository WS";
			}
		}
		private void uRLToolStripMenuItem_Click(object sender, EventArgs e)
		{
			if ( !miURL.Checked ) {
				_workflow.ExtendedProperties.IsDeployedWebServiceURL = true;
				displayDeployedWS();
				//miRepositoryWS.Checked = false;
				//miURL.Checked = true;
				//txtWebService.ReadOnly = false;
				//txtWebService.Text = "";
				//btnSelectWS.Enabled = false;
				//btnSelectWSType.Text = "URL";
			}
		}

		private void UCWorkflow_Enter(object sender, EventArgs e)
		{
			if ( _changedSinceLastHierarchyView ) {
				if ( tabControl1.SelectedTab == tabUsedBy ) {
					usedByHierarchyWorkflow.RepositoryItem = this.RepositoryItem as RepositoryItemBaseEx;
				} else if ( tabControl1.SelectedTab == tabUses ) {
					usingHierarchyWorkflow.RepositoryItem = this.RepositoryItem as RepositoryItemBaseEx;
				}
				_changedSinceLastHierarchyView = false;

			}
		}

		private void tabControl1_Selected(object sender, TabControlEventArgs e)
		{
			if ( e.TabPage == tabUsedBy ) {
				usedByHierarchyWorkflow.RepositoryItem = this.RepositoryItem as RepositoryItemBaseEx;
			} else if ( e.TabPage == tabUses ) {
				usingHierarchyWorkflow.RepositoryItem = this.RepositoryItem as RepositoryItemBaseEx;
			}
		}

		private void txtName_KeyPress(object sender, KeyPressEventArgs e)
		{
			if ( e.KeyChar < (char)32 ) return;
			e.Handled = !Helpers.IsValidCharForName(e.KeyChar);
		}


		#endregion

		#endregion

	}
}
